package game.map
{
	import flash.geom.Point;
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;
	import starling.events.WheelEvent;
	
	/**
	 * @author Kirill Pletnev
	 */
	public class GameCamera
	{
		/**
		 * максимальное значение масштабирования игровой карты
		 */
		private static const SCALING_MAX:Number = 1;
		/**
		 * минимальное значение масштабирования игровой карты
		 */
		private static const SCALING_MIN:Number = 0.5;
		/**
		 * разница маштаба
		 */
		private static const SCALING_DIF:Number = 0.25;
		/**
		 * во сколько раз нужно увеличить масштаб карты
		 */
		private static const SCALING_IN:Number = 1.0 + SCALING_DIF;
		/**
		 * во сколько раз нужно уменьшить масштаб карты
		 */
		private static const SCALING_OUT:Number = 1.0 - SCALING_DIF;
		/**
		 * контроллер для отображения игровой карты
		 */
		private var _visualMap:VisualMap;
		/**
		 * ширина stage
		 */
		private var _stageWidth:int;
		/**
		 * высота stage
		 */
		private var _stageHeight:int;
		/**
		 * Tween для плавного масштабирования игровой карты
		 */
		private var _zoomTween:Tween;
		/**
		 * половина высоты игравой карты
		 */
		private var _mapHalfWidth:int;
		/**
		 * разница между половиной ширины stage и половиной ширины игравой карты
		 */
		private var _difWidthStageAndHalfWidthMap:int;
		/**
		 * разница между половиной высоты stage и половиной высоты игравой карты
		 */
		private var _difHeightStageAndHeightMap:int;
		
		public function GameCamera(visualMap:VisualMap)
		{
			_visualMap = visualMap;
			
			_stageWidth = Starling.current.stage.stageWidth;
			_stageHeight = Starling.current.stage.stageHeight;
			
			updateTempeValues();
			
			visualMap.addEventListener(TouchEvent.TOUCH, onTouch);
			Starling.current.stage.addEventListener(WheelEvent.SCROLL, onMouseWheel);
		}
		
		private function updateTempeValues():void
		{
			_mapHalfWidth = _visualMap.width / 2;
			_difWidthStageAndHalfWidthMap = _stageWidth - _mapHalfWidth;
			_difHeightStageAndHeightMap = _stageHeight - _visualMap.height;
			
			_zoomTween = null;
		}
		
		/**
		 * перемещение камеры к центру игравой карты
		 */
		public function moveToCenter():void
		{
			_visualMap.x = _stageWidth >> 1;
			_visualMap.y = _difHeightStageAndHeightMap >> 1;
		}
		
		private function onTouch(event:TouchEvent):void
		{
			if (event.touches.length == 1)
			{
				var touches:Touch = event.touches[0];
				var location:Point = null;
				
				if (touches.phase == TouchPhase.MOVED)
				{
					location = touches.getLocation(_visualMap);
					
					var oldLocation:Point = touches.getPreviousLocation(_visualMap);
					var dif:Point = location.subtract(oldLocation);
					var x:int = _visualMap.x + dif.x * _visualMap.scaleX;
					var y:int = _visualMap.y + dif.y * _visualMap.scaleY;
					
					if (x >= _difWidthStageAndHalfWidthMap && x <= _mapHalfWidth)
					{
						_visualMap.x = x;
					}
					if (y <= 0 && y >= _difHeightStageAndHeightMap)
					{
						_visualMap.y = y;
					}
				}
			}
		}
		
		private function onMouseWheel(event:WheelEvent):void
		{
			zoom(event.delta > 0, event.localX, event.localY);
		}
		
		public function zoomCenter(isZoomIn:Boolean):void
		{
			zoom(isZoomIn, _stageWidth >> 1, _stageHeight >> 1);
		}
		
		/**
		 *
		 * @param	isZoomIn - если true увеличиваем маштаб игравой карты на DIF_SCALING
		 * 			если false уменьшаем маштаб игравой карты на DIF_SCALING
		 * 
		 * @param	x,y - положение мыши относительно VisualMap 
		 */
		private function zoom(isZoomIn:Boolean, x:int, y:int):void
		{
			var scalingDiv:Number = isZoomIn ? SCALING_IN : SCALING_OUT;
			var scalingOld:Number = _visualMap.scaleX;
			var scalingNew:Number = scalingOld * scalingDiv;
			
			if (scalingNew >= SCALING_MIN && scalingNew <= SCALING_MAX)
			{
				var widht:int = _visualMap.width * scalingDiv;
				var height:int = _visualMap.height * scalingDiv;
				_mapHalfWidth = widht / 2;
				
				if (_stageWidth < widht || _stageHeight < height)
				{
					x = (_visualMap.x - x) * scalingDiv + x;
					y = (_visualMap.y - y) * scalingDiv + y;
					
					if (x > _mapHalfWidth)
					{
						x = _mapHalfWidth;
					}
					if (y > 0)
					{
						y = 0;
					}
					if (x < _stageWidth - _mapHalfWidth)
					{
						x = _stageWidth - _mapHalfWidth;
					}
					if (height + y - _stageHeight < 0)
					{
						y = _stageHeight - height;
					}
					
					if (_zoomTween != null)
					{
						Starling.juggler.remove(_zoomTween);
						_zoomTween = null;
					}
					_zoomTween = new Tween(_visualMap, SCALING_DIF);
					_zoomTween.scaleTo(scalingNew);
					_zoomTween.moveTo(x, y);
					_zoomTween.onComplete = updateTempeValues;
					Starling.juggler.add(_zoomTween);
				}
			}
		}
	}

}